//响应输出为HTML的Ajax请求类
Request.HTML = new Class({

 //继承自Request类
 Extends: Request,

 options: {
  //是否更新
  update: false,
  //是否解释执行字符脚本
  evalscrīpts: true,
  //是否过滤
  filter: false
 },

 //处理HTML代码
 processHTML: function(text){
  //如果请求为完整的HTML页
  var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
  //取<body>与</body>之间的字符
  text = (match) ? match[1] : text;
  
  //创建html的容器节点
  var container = new Element('div');
  
  //返回容器节点,先尝试使用XMLDOM解释HTML节点,失败的话直接设置innerHTML
  return $try(function(){
   //构造一个根节点,因为必须保证让XML片段有根节点
   var root = '<root>' + text + '</root>', doc;
   //IE的处理
   if (Browser.Engine.trident){
    //使用ActiveX控件解释
    doc = new ActiveXObject('Microsoft.XMLDOM');
    //同步加载
    doc.async = false;
    doc.loadXML(root);
   } else {
    //使用标准DOM解释器解释
    doc = new DOMParser().parseFromString(root, 'text/xml');
   }
   //取根节点句柄
   root = doc.getElementsByTagName('root')[0];
   //通过遍历节点,复制到container容器中
   for (var i = 0, k = root.childNodes.length; i < k; i++){
    var child = Element.clone(root.childNodes[i], true, true);
    if (child) container.grab(child);
   }
   return container;
   //XMLDOM解释失败的话直接设置innerHTML
  }) || container.set('html', text);
 },

 //请求成功,覆盖Request类的同名方法
 success: function(text){
  var ōptions = this.options, response = this.response;
  
  //解释出脚本,之后剩下HTML
  response.html = text.stripscrīpts(function(scrīpt){
   response.javascrīpt = scrīpt;
  });
  
  //处理HTML中的节点
  var temp = this.processHTML(response.html);
  
  //绑定节点到返回的对象
  response.tree = temp.childNodes;
  response.elements = temp.getElements('*');
  
  //如果提供过滤标签名,过滤树节点
  if (options.filter) response.tree = response.elements.filter(options.filter);
  //如果指定需要更新的Element,将响应更新到Element
  if (options.update) $(options.update).empty().adopt(response.tree);
  //如果指定解释脚本
  if (options.evalscrīpts) $exec(response.javascrīpt);
  
  //调用父类方法,触发成功事件
  this.onSuccess(response.tree, response.elements, response.html, response.javascrīpt);
 }

});

//为Element添加load属性的setter和getter
Element.Properties.load = {
 
 //setter
 set: function(options){
  //从临时对象取Request.HTML
  var load = this.retrieve('load');
  //如果对象存在,取消(这里的send貌似是load的手误?)
  if (load) send.cancel();
  //缓存Request.HTML的配置参数
  return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options));
 },

 //getter
 get: function(options){
  //如果提供配置参数或者不存在缓存
  if (options || ! this.retrieve('load')){
   //缓存配置参数
   if (options || !this.retrieve('load:options')) this.set('load', options);
   //缓存Request.HTML对象
   this.store('load', new Request.HTML(this.retrieve('load:options')));
  }
  //返回缓存的Request.HTML对象
  return this.retrieve('load');
 }

};

//为Element增加load方法
Element.implement({
 
 //加载远程页面节点到当前Element内
 load: function(){
  //上面的准备工作合取load能得到Request.HTML实例,然后发送
  //注意Array.link的使用,使send的两个参数可以任意排列,并且可选
  this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type}));
  return this;
 }

});